package com.example.layoutmanagerdemo.demo;

import android.view.View;

import androidx.recyclerview.widget.RecyclerView;

/**
 * 自定义layoutManager所需要的方法注释
 */
public interface CustomLayoutManagerApi {

    /**
     * 布置给定适配器中的所有相关子视图。LayoutManager负责项目动画的行为。默认情况下，RecyclerView具有一个非null ItemAnimator，并且启用了简单的项目动画。这意味着对适配器的添加/删除操作将导致动画添加新的或出现的项目，删除或消失的项目以及移动的项目。如果LayoutManager从supportsPredictiveItemAnimations()（默认值）返回false ，并在期间运行正常的布局操作#onLayoutChildren(Recycler, State)，则RecyclerView将具有足够的信息以简单的方式运行这些动画。例如，默认的ItemAnimator DefaultItemAnimator会简单地使视图淡入和淡出，无论是实际添加/删除视图还是由于其他添加/删除操作而将它们移到屏幕上还是移开屏幕。
     * 想要获得更好的项目动画体验的LayoutManager，可以根据项目不在屏幕上时存在的位置将项目动画化到屏幕上和屏幕外，然后LayoutManager应该从返回true supportsPredictiveItemAnimations()并向其中添加其他逻辑 #onLayoutChildren(Recycler, State)。
     * 支持预测动画意味着#onLayoutChildren(Recycler, State)将被调用两次；
     * 一次作为“预”布局步骤，以确定项目在实际布局之前的位置，然后再次进行“实际”布局。在预布置阶段，项目将记住其预布置位置，以使其适当布置。也，removed废品将退还这些物品，以帮助确定其他物品的正确放置。这些删除的项目不应添加到子级列表中，而应用于帮助计算其他视图的正确位置，包括以前不在屏幕上的视图（称为APPEARING视图），但可以确定其布局前屏幕外位置给定有关布局前已移除视图的额外信息。
     * 第二遍布局是实际布局，其中仅将使用未删除的视图。在此过程中，唯一的附加要求是：如果 supportsPredictiveItemAnimations()返回true，则要注意哪些视图在布局之前存在于子列表中，哪些在布局之后不存在（称为DISAPPEARING视图），并适当地定位/布局这些视图，而无需考虑到RecyclerView的实际范围。这允许动画系统知道将这些消失的视图设置为动画的位置。
     * <p>
     * RecyclerView的默认LayoutManager实现已经可以处理动画的所有这些要求。RecyclerView的客户端可以直接使用这些布局管理器之一，也可以查看其onLayoutChildren（）的实现，以了解他们如何考虑APPEARING和DISAPPEARING视图。
     *
     * @param recycler 回收站用于获取位置的潜在缓存视图
     * @param state    RecyclerView的瞬态
     */
    void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state);

    /**
     * LayoutParams为RecyclerView的子级创建一个默认对象。
     * LayoutManager经常会希望使用自定义LayoutParams类型来存储特定于布局的额外信息。客户代码应RecyclerView.LayoutParams为此目的子类化 。
     * <p>
     * 重要提示：如果您使用自己定制的LayoutParams类型，你还必须重写 #checkLayoutParams(LayoutParams)， #generateLayoutParams(android.view.ViewGroup.LayoutParams)和 #generateLayoutParams(android.content.Context, android.util.AttributeSet)。
     *
     * @return 子视图的新LayoutParams
     */
    RecyclerView.LayoutParams generateDefaultLayoutParams();

    /**
     * 使用标准测量策略测量子视图，并考虑父RecyclerView的填充和所有添加的项装饰。
     * 如果RecyclerView可以在任意一个维度中滚动，则调用者可以将widthUsed或heightUsed参数传递为0，因为它们将是无关紧要的。
     *
     * @param child      要查看的子视图
     * @param widthUsed  其他视图当前占用的像素宽度（如果有）
     * @param heightUsed 其他视图当前消耗的高度（以像素为单位）
     */
    void measureChild(View child, int widthUsed, int heightUsed);

    /**
     * 使用标准测量策略来测量子视图，并考虑父RecyclerView的填充，任何添加的项装饰和子边距。
     * 如果RecyclerView可以在任意一个维度中滚动，则调用者可以将widthUsed或heightUsed参数传递为0，因为它们将是无关紧要的。
     *
     * @param child      要查看的子视图
     * @param widthUsed  其他视图当前占用的像素宽度（如果有）
     * @param heightUsed 其他视图当前消耗的高度（以像素为单位）
     */
    void measureChildWithMargins(View child, int widthUsed, int heightUsed);

    /**
     * 返回给定子级的测量宽度，再加上所应用的任何inset的附加大小ItemDecorations。
     *
     * @param child 子视图查询
     * @return 子视图的测得宽度加上ItemDecoration insets
     */
    int getDecoratedMeasuredWidth(View child);

    /**
     * 返回给定子级的测量高度，再加上所应用的任何inset的附加大小ItemDecorations。
     *
     * @param child 子视图查询
     * @return 子视图的测得高度加上ItemDecoration insets
     */
    int getDecoratedMeasuredHeight(View child);


    /**
     * 使用包含任何当前坐标的坐标在RecyclerView中布置给定的子视图ItemDecorations。
     *
     * @param child  子视图布置
     * @param left   左侧，包括decoration insets
     * @param top    顶部边缘，包括decoration insets
     * @param right  右边缘，包括decoration insets
     * @param bottom 底边，包括decoration insets
     */
    void layoutDecorated(View child, int left, int top, int right, int bottom);

    /**
     * 使用包括任何当前ItemDecorations和边距的坐标在RecyclerView中布置给定的子视图。
     *
     * @param child  子视图布置
     * @param left   左边缘，带有decoration insets和左页边距
     * @param top    顶部边缘，包括decoration insets和顶部边缘
     * @param right  右侧边缘，包括decoration insets和右侧边距
     * @param bottom 底部边缘，包括decoration insets和底部边距
     */
    void layoutDecoratedWithMargins(View child, int left, int top, int right, int bottom);


    /**
     * 分离子视图并将其添加到Recycler's scrap 堆。
     * scrap 视图可以使其重新绑定并重新使用以显示更新的或不同的数据。
     *
     * @param child    子视图要拆下并报废
     * @param recycler 回收商将新的 scrap 视图存入
     */
    void detachAndScrapView(View child, RecyclerView.Recycler recycler);

    /**
     * 分离子视图并将其添加到Recycler's scrap 堆。
     * scrap 视图可以使其重新绑定并重新使用以显示更新的或不同的数据。
     *
     * @param index    分离和报废的子视图的索引
     * @param recycler 回收商将新的 scrap 视图存入
     */
    void detachAndScrapViewAt(int index, RecyclerView.Recycler recycler);

    /**
     * 暂时分离并废弃所有当前附加的子视图。视图将被废弃到给定的回收站中。回收者可能更喜欢在其他先前回收的视图之前重用scrap视图。
     *
     * @param recycler 回收商将scrap视图
     */
    void detachAndScrapAttachedViews(RecyclerView.Recycler recycler);

    /**
     * 删除子视图，然后使用给定的回收器对其进行回收。
     *
     * @param child    删除并回收子视图
     * @param recycler 回收者用来回收子视图
     */
    void removeAndRecycleView(View child, RecyclerView.Recycler recycler);

    /**
     * 删除子视图，然后使用给定的回收器对其进行回收。
     *
     * @param index    删除和回收子视图的索引
     * @param recycler 回收者用来回收子视图
     */
    void removeAndRecycleViewAt(int index, RecyclerView.Recycler recycler);

    /**
     * 删除所有视图并使用给定的回收器回收它们。
     * 如果您还想清除缓存的视图，则也应该调用RecyclerView.Recycler.clear()。
     * <p>
     * 如果视图标记为“ignored”，则不会删除或回收它。
     *
     * @param recycler 回收者用来管理子视图
     */
    void removeAndRecycleAllViews(RecyclerView.Recycler recycler);

    /**
     * 查询当前是否支持水平滚动。默认实现返回false。
     *
     * @return 如果此LayoutManager可以水平滚动当前内容，则为True
     */
    boolean canScrollHorizontally();

    /**
     * 查询当前是否支持垂直滚动。默认实现返回false。
     *
     * @return 如果此LayoutManager可以垂直滚动当前内容，则为True
     */
    boolean canScrollVertically();

    /**
     * 在屏幕坐标中水平滚动dx像素并返回移动距离。默认实现不执行任何操作，并返回0。
     *
     * @param dx       滚动距离，以像素为单位。X随着滚动位置向右移动而增加。
     * @param recycler 回收站用于获取位置的潜在缓存视图
     * @param state    RecyclerView的瞬态
     * @return 实际距离滚动。如果dx为负，并且朝该方向滚动，则返回值将为负。 Math.abs(result)如果达到边界，则可能小于dx。
     */
    int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state);

    /**
     * 垂直滚动屏幕坐标中的dy像素，然后返回移动的距离。默认实现不执行任何操作，并返回0。
     *
     * @param dy       滚动像素的距离。Y随着滚动位置接近底部而增加。
     * @param recycler 回收站用于获取位置的潜在缓存视图
     * @param state    RecyclerView的瞬态
     * @return 实际距离滚动。如果dy为负，并且沿该方向滚动，则返回值将为负。 Math.abs(result)如果达到边界，则可能小于dy。
     */
    int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state);

}